#include "bk_private/bk_init.h"
#include <components/system.h>
#include <os/os.h>
#include <components/shell_task.h>

#include "media_service.h"
#include "driver/media_types.h"
#include <modules/jpeg_decode_sw.h>
#include <modules/tjpgd.h>
#include <driver/uvc_camera.h>
#include "bkwl_common.h"
#include "bkwl_camera.h"

#include "media_app.h"
#include "media_evt.h"

bk_uvc_config_t uvc_config_info_param = {0};
sw_jpeg_dec_res_t result;

media_camera_device_t camera_device = {
	.type = UVC_CAMERA,
	.mode = JPEG_MODE,
	.fmt = PIXEL_FMT_JPEG,
	.info.fps = FPS25,
	.info.resolution.width = 800,
	.info.resolution.height = 480,
};

static void media_checkout_uvc_device_info(bk_uvc_device_brief_info_t *info, uvc_state_t state)
{
	if (state == UVC_CONNECTED)
	{
		uint8_t format_index = 0;
		uint8_t frame_num = 0;
		uint8_t index = 0, i = 0;
		uvc_config_info_param.vendor_id = info->vendor_id;
		uvc_config_info_param.product_id = info->product_id;
		LOGI("%s uvc_get_param VID:0x%x\r\n", __func__, info->vendor_id);
		LOGI("%s uvc_get_param PID:0x%x\r\n", __func__, info->product_id);

		format_index = info->format_index.mjpeg_format_index;
		frame_num = info->all_frame.mjpeg_frame_num;
		if (format_index > 0)
		{
			LOGI("%s uvc_get_param MJPEG format_index:%d\r\n", __func__, format_index);
			for (index = 0; index < frame_num; index++)
			{
				LOGI("uvc_get_param MJPEG width:%d heigth:%d index:%d\r\n",
					 info->all_frame.mjpeg_frame[index].width,
					 info->all_frame.mjpeg_frame[index].height,
					 info->all_frame.mjpeg_frame[index].index);
				for (i = 0; i < info->all_frame.mjpeg_frame[index].fps_num; i++)
				{
					LOGI("uvc_get_param MJPEG fps:%d\r\n", info->all_frame.mjpeg_frame[index].fps[i]);
				}

				if (info->all_frame.mjpeg_frame[index].width == camera_device.info.resolution.width && info->all_frame.mjpeg_frame[index].height == camera_device.info.resolution.height)
				{
					uvc_config_info_param.frame_index = info->all_frame.mjpeg_frame[index].index;
					uvc_config_info_param.fps = info->all_frame.mjpeg_frame[index].fps[0];
					uvc_config_info_param.width = camera_device.info.resolution.width;
					uvc_config_info_param.height = camera_device.info.resolution.height;
				}
			}
		}

		uvc_config_info_param.format_index = format_index;

		if (media_app_set_uvc_device_param(&uvc_config_info_param) != BK_OK)
		{
			LOGE("%s, failed\r\n, __func__");
		}
	}
	else
	{
		LOGI("%s, %d\r\n", __func__, state);
	}
}

static int nStatus = 0;
static void media_read_frame_info_callback(frame_buffer_t *frame)
{
#if 0
	os_printf("##MJPEG:camera_type:%d(1:dvp 2:uvc) frame_id:%d, length:%d, frame_addr:%p \r\n", frame->type, frame->sequence,
			  frame->length, frame->frame);
	bk_jpeg_get_img_info(frame->length, frame->frame, &result);
	os_printf("##DECODE:pixel_x:%d, pixel_y:%d\n\r", result.pixel_x, result.pixel_y);
	os_printf("rotate_angle:%d(0:0 1:90 2:180 3:270)\n\r", jd_get_rotate());
	os_printf("byte_order:%d(0:little endian 1:big endian)\n\r", jd_get_byte_order());
	switch (jd_get_format())
	{
	case JD_FORMAT_RGB888:
		os_printf("out_fmt:RGB888\r\n\n");
		break;

	case JD_FORMAT_RGB565:
		os_printf("out_fmt:RGB565\r\n\n");
		break;

	case JD_FORMAT_Grayscale:
		os_printf("out_fmt:Grayscale\r\n\n");
		break;

	case JD_FORMAT_YUYV:
		os_printf("out_fmt:YUYV\r\n\n");
		break;

	case JD_FORMAT_VYUY:
		os_printf("out_fmt:VYUY\r\n\n");
		break;

	case JD_FORMAT_VUYY:
		os_printf("out_fmt:VUYY\r\n\n");
		break;

	default:
		break;
	}
#else
	if (bkwl_main->camera.image_print == 1)
	{
		bkwl_main->camera.image_print = 0;
		bkwl_print_frame(frame);
	}
	if (bkwl_main->camera.image_get == 1)
	{
		bkwl_main->camera.image_get = 0;
		bkwl_main->camera.image_cur.len = 0;
		if (bkwl_main->camera.image_cur.buffer != NULL)
		{
			tprintf("twh get image frame  free data \n");
			free(bkwl_main->camera.image_cur.buffer);
			bkwl_main->camera.image_cur.buffer = NULL;
		}
		if (bkwl_main->camera.image_cur.buffer == NULL)
		{
			tprintf("twh get image frame  malloc data,len=%d\n", frame->length);
			bkwl_main->camera.image_cur.buffer = (uint8_t *)malloc(frame->length + 1);
		}
		memcpy(bkwl_main->camera.image_cur.buffer, frame->frame, frame->length);
		bkwl_main->camera.image_cur.len = frame->length;
		tprintf("twh get image frame data,len=%d\n", frame->length);
	}
	nStatus++;
#endif
}

bkwl_image_t *bkwl_camera_get_image(void)
{
	bkwl_image_t *ret = NULL;
	bkwl_main->camera.image_get = 1;
	int sleep_num = 0;
	while (bkwl_main->camera.image_get == 1 && sleep_num < 200)
	{
		rtos_delay_milliseconds(10);
		sleep_num++;
	}
	if (bkwl_main->camera.image_get == 0 && sleep_num < 200 && bkwl_main->camera.image_cur.len > 0)
	{
		ret = &bkwl_main->camera.image_cur;
		tprintf("bkwl_camera_get_image get image frame\n");
		tprintf("bkwl_camera_get_image get image ret->len=%d\n", ret->len);
	}
	return ret;
}

void bkwl_camera_get_print(void)
{
	bkwl_main->camera.image_get = 1;
	return;
}

void bkwl_camera_uvc_init(void)
{
	bk_err_t ret = BK_OK;
	bk_jpeg_dec_sw_init(NULL, 0);

	ret = media_app_uvc_register_info_notify_cb(media_checkout_uvc_device_info);
	if (ret != BK_OK)
	{
		os_printf("media_app_uvc_register_info_notify_cb failed\r\n");
	}

	ret = media_app_camera_open(&camera_device);
	if (ret != BK_OK)
	{
		os_printf("media_app_camera_open failed\r\n");
	}

	ret = media_app_register_read_frame_callback(camera_device.fmt, media_read_frame_info_callback);
	if (ret != BK_OK)
	{
		os_printf("media_app_register_read_frame_callback failed\r\n");
	}
}

bk_err_t bkwl_print_frame(frame_buffer_t *frame)
{

	bk_err_t ret = BK_OK;
	printf("show pic data start:\n\n");
	for (int i = 0; i < frame->length; i++)
	{
		tprintf("%02x", (unsigned char)(0xff & (unsigned char)(frame->frame[i])));
	}
	printf("\n\nshow pic data end:\n\n");
	return ret;
}